package com.wzdigit.wms.raw.service.gdn;

import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wzdigit.framework.Shift;
import com.wzdigit.wms.basic.client.Pager;
import com.wzdigit.wms.basic.client.PagerInfo;
import com.wzdigit.wms.basic.client.request.outstock.CancelPickMaterialRequest;
import com.wzdigit.wms.basic.client.request.transfer.SearchGdnDtlRequest;
import com.wzdigit.wms.basic.client.request.transfer.SearchGdnHeaderRequest;
import com.wzdigit.wms.basic.client.response.Result;
import com.wzdigit.wms.basic.client.response.transfer.GdnDtlGoodsListResponse;
import com.wzdigit.wms.basic.client.response.transfer.GdnDtlListResponse;
import com.wzdigit.wms.basic.client.response.transfer.GdnHeaderListResponse;
import com.wzdigit.wms.basic.enums.*;
import com.wzdigit.wms.basic.mapper.core.basic.WarehouseMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.GdnDtlGoodsMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.GdnDtlMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.GdnHeaderMapper;
import com.wzdigit.wms.basic.util.HttpSessionUtil;
import com.wzdigit.wms.basic.util.enums.SystemModuleEnum;
import com.wzdigit.wms.common.entity.ExcelExportConfig;
import com.wzdigit.wms.common.entity.StatusCode;
import com.wzdigit.wms.common.utils.HttpExcel;
import com.wzdigit.wms.raw.client.response.gdn.report.CancelGdnResponse;
import com.wzdigit.wms.raw.client.response.gdn.report.GdnExportExt;
import com.wzdigit.wms.raw.client.response.gdn.report.GdnHeaderListNewResponse;
import com.wzdigit.wms.raw.client.response.gdn.report.RawGdnEnums;
import com.wzdigit.wms.raw.mapper.gdn.report.GdnReportMapper;
import com.wzdigit.wms.raw.service.outstock.PickMaterialService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 发货单-服务类
 * @author yangdongjie
 * @GdnService.java
 * @2021年2月24日下午3:25:03
 */
@Service
@Slf4j
public class GdnService {

	//private List<String> gdnTypeList= Arrays.asList("D02","D12","D13","D14","D15","D16","D17","D18","D21","D22","D23","D24","D25","D26","D27","D28");
	
	@Autowired
	private GdnHeaderMapper gdnHeaderMapper;

	
	@Autowired
	private GdnDtlMapper gdnDtlMapper;

	@Autowired
	GdnDtlGoodsMapper gdnDtlGoodsMapper;

	@Autowired
	WarehouseMapper warehouseMapper ;

	@Autowired
	private GdnReportMapper gdnReportMapper;

	@Autowired
	private PickMaterialService pickMaterialService;



	
	/**
	 * 发货单列表
	 * @param dto
	 * @return
	 * 【是否允许打印预留单】余留数量 > 0 
	 * 【是否允许打印发货单】只要有一笔明细仓库不为空
	 */
	public PagerInfo<List<GdnHeaderListNewResponse>> listGdnHeader(SearchGdnHeaderRequest dto, Pager<?> pager) {
//		List<String> gdnTypeList = GdnTypeEnum.getEnumByType(GDN_TYPE);
		Page<?> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<GdnHeaderListNewResponse>> pagerInfo = new PagerInfo<List<GdnHeaderListNewResponse>>();

        // 发料时间
        Date shipDateStart = null, shipDateEnd = null;
		if(dto.getShipTimeStart() != null) {
			shipDateStart = new Date(dto.getShipTimeStart());
		}
		if(dto.getShipTimeEnd() != null) {
			shipDateEnd = new Date(dto.getShipTimeEnd());
		}

        // 审核开始时间和结束时间
        Date approvedDateStart = null, approvedDateEnd = null;
        if(dto.getApprovedTimeStart() != null) {
			approvedDateStart = new Date(dto.getApprovedTimeStart());
        }
		if(dto.getApprovedTimeEnd() != null) {
			approvedDateEnd = new Date(dto.getApprovedTimeEnd());
		}


        // 发货单明细状态
        List<Integer> gdnDtlStatusList = new ArrayList<>();
        if(dto.getIsWaitPick() != null && dto.getIsWaitPick()) {	// 待拣货
        	gdnDtlStatusList.add(GdnDtlStatusEnum.WAITPICK.code);
        }
        if(dto.getIsNotFinish() != null && dto.getIsNotFinish()) {	// 未完成
        	gdnDtlStatusList.add(GdnDtlStatusEnum.CREATE.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.HASDONE.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.WAITPICK.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.PICKING.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.WAITLOAD.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.LOADING.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.SHIPMENTING.code);
        }

        List<GdnHeaderListNewResponse> list = new ArrayList<>(0);
        /*if(dto.getGdnType() == null || GdnTypeEnum.SALES_OUT.code.equals(dto.getGdnType())){
        	dto.setGdnType(GdnTypeEnum.SALES_OUT.code);
        }*/
		List<String> gdnTypeList = GdnTypeEnum.getCodeListBySystemModule(SystemModuleEnum.RAW);
		list = gdnReportMapper.selectAllRawNew(dto, gdnDtlStatusList, shipDateStart, shipDateEnd, approvedDateStart, approvedDateEnd,gdnTypeList);
        for(GdnHeaderListNewResponse item : list){
        	//查询明细
			List<String>  warehourses = gdnReportMapper.selectDistinctWareHouseNew(item.getGdnHeaderId());
            String ss = warehourses.stream().collect(Collectors.joining(","));

			item.setWarehouse(ss);
		}
        pagerInfo.setTotalCount(page.getTotal());
        pagerInfo.setItems(list);
		return pagerInfo;
    }
	
	/**
	 * 发货单明细列表
	 * @param dto
	 * @return
	 * 【是否允许分配库存】	UDF1 = NO
	 * 【是否允许取消分配库存】	(UDF1 = YES & 拣货任务标识 = 0（未生成）) || (UDF1 = NO & WHS_ID != NULL)
	 * 【是否允许排柜】		UDF1 = YES & 发货单明细排柜状态 = 0(未排柜) & 发货单明细状态 != (0：取消、6：装柜中、7：已发运、8：关闭)
	 */
	public PagerInfo<List<GdnDtlListResponse>> listGdnDtl(SearchGdnDtlRequest dto, Pager<?> pager) {
    	Page<?> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
        PagerInfo<List<GdnDtlListResponse>> pagerInfo = new PagerInfo<List<GdnDtlListResponse>>();
        
        // 发货单明细状态
        List<Integer> gdnDtlStatusList = new ArrayList<>();
        if(dto.getIsWaitPick() != null && dto.getIsWaitPick()) {	// 待拣货
        	gdnDtlStatusList.add(GdnDtlStatusEnum.WAITPICK.code);
        }
        if(dto.getIsNotFinish() != null && dto.getIsNotFinish()) {	// 未完成
        	gdnDtlStatusList.add(GdnDtlStatusEnum.CREATE.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.HASDONE.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.WAITPICK.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.PICKING.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.WAITLOAD.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.LOADING.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.SHIPMENTING.code);
        	gdnDtlStatusList.add(GdnDtlStatusEnum.SHIPMENTED.code);
        }
        
        List<GdnDtlListResponse> list = gdnDtlMapper.selectAllRaw(dto.getGdnHeaderId(), gdnDtlStatusList);
        for (GdnDtlListResponse one : list) {
			if(one.getAllowAloc()) {
				one.setIsCreatePicktaskText("否（未预配）");
			} else if (!Objects.equals(PicktaskFlagEnum.UN_CREATED.code, one.getPickTaskFlag())) {
				one.setIsCreatePicktaskText("否（已生成）");
			} else {
				one.setIsCreatePicktaskText("是");
			}

		}
        pagerInfo.setItems(list);
        pagerInfo.setTotalCount(page.getTotal());
		return pagerInfo;
    }


	/**
	 * 发货单明细货品清单列表
	 * @param gdnDtlId
	 * @param pager
	 * @return
	 */
	public <T> PagerInfo<List<GdnDtlGoodsListResponse>> searchGdnDtlGoods(Integer gdnDtlId, Pager<T> pager) {
		Page<?> page = PageHelper.offsetPage(pager.getSkipCount(), pager.getMaxResultCount());
		PagerInfo<List<GdnDtlGoodsListResponse>> pagerInfo = new PagerInfo<List<GdnDtlGoodsListResponse>>();
		List<GdnDtlGoodsListResponse> list = gdnDtlGoodsMapper.selectAllRaw(gdnDtlId);
		pagerInfo.setItems(list);
		pagerInfo.setTotalCount(page.getTotal());
		return pagerInfo;
	}

    /* 获取发货单主表明细行号和物料编码
        * @param gdnHeaderId 发货单主表ID
        * @return java.util.List<com.wzdigit.wms.basic.client.response.transfer.GdnDtlListResponse>
        * @author shuaic
        * @date 2021/7/14 13:44
    */
	public List<GdnDtlListResponse> listGdnDtlLineNoAndSkuCode(Integer gdnHeaderId) {
		 try {
			 List<GdnDtlListResponse> gdnDtls = gdnDtlMapper.selectDtlLineNoAndSkuCodeByHeaderId(gdnHeaderId);
             return gdnDtls;
		 }catch (Exception e){
		 	e.printStackTrace();
			 Shift.fatal(StatusCode.SERVER_UNKNOWN_ERROR);
			 return null;
		 }

	}


	public XSSFWorkbook exportGdn(SearchGdnHeaderRequest dto) {
		List<String> gdnTypeList = GdnTypeEnum.getCodeListBySystemModule(SystemModuleEnum.RAW);
		XSSFWorkbook workbook = null;
		try {
			// 发料时间
			Date shipDateStart = null, shipDateEnd = null;
			if(dto.getShipTimeStart() != null) {
				shipDateStart = new Date(dto.getShipTimeStart());
			}
			if(dto.getShipTimeEnd() != null) {
				shipDateEnd = new Date(dto.getShipTimeEnd());
			}

			// 审核开始时间和结束时间
			Date approvedDateStart = null, approvedDateEnd = null;
			if(dto.getApprovedTimeStart() != null) {
				approvedDateStart = new Date(dto.getApprovedTimeStart());
			}
			if(dto.getApprovedTimeEnd() != null) {
				approvedDateEnd = new Date(dto.getApprovedTimeEnd());
			}
			// 发货单明细状态
			List<Integer> gdnDtlStatusList = new ArrayList<>();
			if(dto.getIsWaitPick() != null && dto.getIsWaitPick()) {	// 待拣货
				gdnDtlStatusList.add(GdnDtlStatusEnum.WAITPICK.code);
			}
			if(dto.getIsNotFinish() != null && dto.getIsNotFinish()) {	// 未完成
				gdnDtlStatusList.add(GdnDtlStatusEnum.CREATE.code);
				gdnDtlStatusList.add(GdnDtlStatusEnum.HASDONE.code);
				gdnDtlStatusList.add(GdnDtlStatusEnum.WAITPICK.code);
				gdnDtlStatusList.add(GdnDtlStatusEnum.PICKING.code);
				gdnDtlStatusList.add(GdnDtlStatusEnum.WAITLOAD.code);
				gdnDtlStatusList.add(GdnDtlStatusEnum.LOADING.code);
				gdnDtlStatusList.add(GdnDtlStatusEnum.SHIPMENTING.code);
			}

			List<GdnHeaderListResponse> list = new ArrayList<>(0);
			list = gdnHeaderMapper.selectAllRaw(dto, gdnDtlStatusList, shipDateStart, shipDateEnd, approvedDateStart, approvedDateEnd,gdnTypeList);
			for(GdnHeaderListResponse item :list){
				//订单状态
				item.setStatusCn(GdnHeaderStatusEnum.getEnumByCode(item.getStatus()).getEnumName() );
				item.setGdnTypeCn(GdnTypeEnum.getEnumByCode(item.getGdnType()).getEnumName());
			}
			List<ExcelExportConfig> configs = new ArrayList<>();
			configs.add(new ExcelExportConfig("出库单号", "gdnNo", 120));
			configs.add(new ExcelExportConfig("订单状态", "statusCn", 120));
			configs.add(new ExcelExportConfig("单据类型", "gdnTypeCn", 120));
			configs.add(new ExcelExportConfig("关联单号", "sourceShipNotice", 120));
			//configs.add(new ExcelExportConfig("发料仓库", "asnNo", 120));
			configs.add(new ExcelExportConfig("领料部门", "rcvDept", 120));
			configs.add(new ExcelExportConfig("供应商", "consigneeName", 120));
			configs.add(new ExcelExportConfig("优先级", "priority", 120));
			configs.add(new ExcelExportConfig("发料时间", "shipDate", 120));
			configs.add(new ExcelExportConfig("制单时间", "createTime", 120));
			configs.add(new ExcelExportConfig("审核时间", "approvedTime", 120));
			configs.add(new ExcelExportConfig("制单人", "createUser", 120));
			configs.add(new ExcelExportConfig("审核人", "approvedUser", 120));
			configs.add(new ExcelExportConfig("备注", "comments", 120));
			workbook = HttpExcel.newListToExcel(list, configs);



		}catch (Exception e){
			e.printStackTrace();
			Shift.fatal(StatusCode.SERVER_UNKNOWN_ERROR);

		}
		return workbook;

	}

	public XSSFWorkbook exportGdnNew(SearchGdnHeaderRequest dto) {
		List<String> gdnTypeList = GdnTypeEnum.getCodeListBySystemModule(SystemModuleEnum.RAW);
		XSSFWorkbook workbook = null;
		try {
			// 发料时间
			Date shipDateStart = null, shipDateEnd = null;
			if(dto.getShipTimeStart() != null) {
				shipDateStart = new Date(dto.getShipTimeStart());
			}
			if(dto.getShipTimeEnd() != null) {
				shipDateEnd = new Date(dto.getShipTimeEnd());
			}

			// 审核开始时间和结束时间
			Date approvedDateStart = null, approvedDateEnd = null;
			if(dto.getApprovedTimeStart() != null) {
				approvedDateStart = new Date(dto.getApprovedTimeStart());
			}
			if(dto.getApprovedTimeEnd() != null) {
				approvedDateEnd = new Date(dto.getApprovedTimeEnd());
			}
			// 发货单明细状态
			List<Integer> gdnDtlStatusList = new ArrayList<>();
			if(dto.getIsWaitPick() != null && dto.getIsWaitPick()) {	// 待拣货
				gdnDtlStatusList.add(GdnDtlStatusEnum.WAITPICK.code);
			}
			if(dto.getIsNotFinish() != null && dto.getIsNotFinish()) {	// 未完成
				gdnDtlStatusList.add(GdnDtlStatusEnum.CREATE.code);
				gdnDtlStatusList.add(GdnDtlStatusEnum.HASDONE.code);
				gdnDtlStatusList.add(GdnDtlStatusEnum.WAITPICK.code);
				gdnDtlStatusList.add(GdnDtlStatusEnum.PICKING.code);
				gdnDtlStatusList.add(GdnDtlStatusEnum.WAITLOAD.code);
				gdnDtlStatusList.add(GdnDtlStatusEnum.LOADING.code);
				gdnDtlStatusList.add(GdnDtlStatusEnum.SHIPMENTING.code);
			}

			List<GdnExportExt> list = gdnReportMapper.exportGdn(dto, gdnDtlStatusList, shipDateStart, shipDateEnd, approvedDateStart, approvedDateEnd,gdnTypeList);
			Integer flag1=0;Integer flag2=1;
			for(GdnExportExt item :list){
				//订单状态
				item.setHedaderstatusStr(GdnHeaderStatusEnum.getEnumByCode(item.getHedaderstatus()).getEnumName() );
				item.setGdnTypeStr(GdnTypeEnum.getEnumByCode(item.getGdnType()).getEnumName());
				if (flag1.equals(item.getPriority())){
					item.setPriorityStr("普通");
				}else if (flag2.equals(item.getPriority())){
					item.setPriorityStr("紧急");
				}
				if (GdnTypeEnum.D21.code.equals(item.getGdnType())){
					item.setSourceShipNoticeItem(item.getGdnRef5());
				}
			}
			List<ExcelExportConfig> configs = new ArrayList<>();
			configs.add(new ExcelExportConfig("出库单号", "gdnNo", 120));
			configs.add(new ExcelExportConfig("出库单行号", "gdnLineNo", 120));
			//主档
			configs.add(new ExcelExportConfig("订单状态", "hedaderstatusStr", 120));
			configs.add(new ExcelExportConfig("单据类型", "gdnTypeStr", 120));
			configs.add(new ExcelExportConfig("关联单号", "dataSource", 120));
			configs.add(new ExcelExportConfig("发料仓库", "whsName", 120));
			configs.add(new ExcelExportConfig("领料部门", "rcvDept", 120));
			configs.add(new ExcelExportConfig("供应商", "consigneeName", 120));
			configs.add(new ExcelExportConfig("优先级", "priorityStr", 120));
			configs.add(new ExcelExportConfig("发料时间", "shipDate", 120));
			configs.add(new ExcelExportConfig("制单时间", "hedaerCreateTime", 120));
			configs.add(new ExcelExportConfig("审核时间", "approvedTime", 120));
			configs.add(new ExcelExportConfig("制单人", "hedaerCreateUser", 120));
			configs.add(new ExcelExportConfig("审核人", "approvedUser", 120));
			configs.add(new ExcelExportConfig("备注", "comments", 120));
			//明细
			configs.add(new ExcelExportConfig("物料编码", "skuCode", 120));
			configs.add(new ExcelExportConfig("物料描述", "skuDesc", 120));
			configs.add(new ExcelExportConfig("物料规格", "skuSpec", 120));
			configs.add(new ExcelExportConfig("关联单行号", "sourceShipNoticeItem", 120));
			configs.add(new ExcelExportConfig("出库数量", "orderQty", 120));
			configs.add(new ExcelExportConfig("拣料数量", "pickQty", 120));
			configs.add(new ExcelExportConfig("发料数量", "shipQty", 120));
			configs.add(new ExcelExportConfig("单位", "unit", 120));
			configs.add(new ExcelExportConfig("创建时间", "dtlCreateUser", 120));
			configs.add(new ExcelExportConfig("创建人", "dtlCreateTime", 120));
			workbook = HttpExcel.newListToExcel(list, configs);



		}catch (Exception e){
			e.printStackTrace();
			Shift.fatal(StatusCode.SERVER_UNKNOWN_ERROR);

		}
		return workbook;

	}

    //取消送货单，只能对出库单主档状态为新建或者出库数量=0的单据进行取消
	//对于已经拣货的发货单，逆向执行取消拣货
	@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
	public Result<?> cacnelRawGdn(List<BigDecimal> headerIds,HttpServletRequest servletRequest,
								  HttpServletResponse servletResponse) throws Exception{
		if (CollectionUtil.isEmpty(headerIds)){
			Shift.fatal("请勾选发货单再点击[取消送货单]按钮!");
		}
		//查询要取消的送货单
		List<CancelGdnResponse> cancelGdnList = gdnReportMapper.selectCacncelGdn(headerIds);
		//分组：状态不为新建的送货单
		List<CancelGdnResponse> notNewCancelGdnList = cancelGdnList.stream().filter(t -> !t.getStatus().
				equals(GdnHeaderStatusEnum.CREATE.code)).collect(Collectors.toList());
		List<CancelGdnResponse> pickCancelGdnList=new ArrayList<>();
		if (!CollectionUtil.isEmpty(notNewCancelGdnList)){
			for (CancelGdnResponse notNewCancelGdn : notNewCancelGdnList) {
				if(BigDecimal.ZERO.compareTo(notNewCancelGdn.getShipQtys()) == -1){
					Shift.fatal("发货单["+notNewCancelGdn.getGdnNo()+"]存在出库SN，无法取消!");
				}
			}
			//分组：状态不为新建，出库数量=0，拣货数量>0的送货单
			pickCancelGdnList=notNewCancelGdnList.stream().filter(t ->
					(BigDecimal.ZERO.compareTo(t.getPickQtys()) == -1)).
							collect(Collectors.toList());
		}
		//取消拣货
		if (!CollectionUtil.isEmpty(pickCancelGdnList)){
			List<BigDecimal> collect = pickCancelGdnList.stream().
					map(t -> t.getGdnHeaderId()).collect(Collectors.toList());
			List<CancelPickMaterialRequest> cancelGdnRepostGoods = gdnReportMapper.selectCacncelGdnGoods(collect);
			pickMaterialService.cancelPick(cancelGdnRepostGoods,servletRequest,servletResponse,true,null);
		}
		//更新送货单状态
		gdnReportMapper.updateCacncelGdnHeader(headerIds, GdnHeaderStatusEnum.CANCEL.code,
				HttpSessionUtil.getLoginName(servletRequest),new Date());

		return new Result<>("取消出库单成功!");
	}

	//查询出库单据类型下拉框
	public List<RawGdnEnums> getGdnEnumsList(){
		List<String> gdnTypeList = GdnTypeEnum.getCodeListBySystemModule(SystemModuleEnum.RAW);
		List<RawGdnEnums> datas=new ArrayList<>();
		for (String gdnTypeString : gdnTypeList) {
			GdnTypeEnum gdnTypeEnum = GdnTypeEnum.getEnumByCode(gdnTypeString);
			if (gdnTypeEnum!=null){
				RawGdnEnums data=new RawGdnEnums();
				data.setCode(gdnTypeString);
				data.setEnumName(gdnTypeEnum.getEnumName());
				datas.add(data);
			}
		}
		return datas;
	}

}